[入門] EBSを暗号化しよう
おはようございます、もきゅりんです。 昨夜くらいから目が痒くなってまいりました。春ですね...祭典の季節です。 ストラヴィンスキーです。 春になると、例年ちょっとおかしな人たちが出てきますよね。
そう、そんなときに大事なのが、セキュリティ管理。 セキュリティ管理といえば暗号化、ということで、今回はKMSに触れながらEBSの暗号化です。
実は、KMS関連で諸々触っていたのですが、 それを一記事にまとめると大変な長さになってきそうなので、 区切り良くまとめながら小出しにしていきます。
やること
- KMSキーを作成
-
EBSを暗号化
-
後片付けを忘れずに
1 KMSキーを作成
それではまずはともあれ、KMSでキーを作成しましょう。しっかりリージョンを選択しときましょう。
エイリアスを設定します。 (CLIからだとキーを作成した後にエイリアスを設定するみたいでめんどいので、手動で作ります。 (2019年2月20日現在))
この後は以下のような流れです。
・ タグを設定します。このタグからコスト配分レポートにも利用できます。
・ このキーを管理(編集・削除)できる IAM ユーザーとロールを選択
・ このキーを使用してデータを暗号化および復号化できる IAM ユーザーとロールを選択
すると、キーが出来ました! そしたら、このKeyIDは大事なので取っておきましょう。
2 EBSを暗号化
で、今回のターゲットはEBSです。 EBSの暗号化については、下記表のようにインスタンスのステータスによって対応が異なっています。
Status | 1 | 2 | 3 | 4 |
Running | AMI作成 | そのAMIをコピーしてSnapshotの暗号化を設定 | コピーしたAMIからインスタンスを起動 | - |
stopped | Snapshot作成 | そのSnapshotをコピーして暗号化する | コピーしたSnapshotからボリュームを作成 | 新ボリュームをインスタンスにアタッチ |
いやー...なかなか煩雑ですね。。
実際、手でポチポチ...あるいはCLIからちょこちょこ叩きながら確認してみたのですが、 作成が完了したのを見届けると、あれ、次何やるんだっけ...?みたいな感じになりました。。 (同じような作業が多いからですかね)
ということで、下記、実用を全く想定していないスクリプトをチョロっと書きました。 やっていることは上記表をそのままやっているだけです。
なお、稼働中のEBSの暗号化でいうと、 弊社記事に[入門] 稼働中のEC2インスタンスのEBS Volumeを暗号化する [EC2インスタンス] もございます。(こちらはストレージのI/Oもしっかり考慮された完成度高めの記事です。)
必要なのは、対象のインスタンス名と、先ほど作成したKMSのキーIDです。 (インスタンスにはアタッチされているボリュームは1つと想定しています。例外処理とかロールバックとか冪等性とかないのでお気を付けくだしー。)
あ、jqを利用しているので、もしなかったらMacの人はhomebrew でインストールしてね!
$ brew install jq
それとAWSにはAWS CLIでアクセスできる環境だと信じています!
では、KMSを設定するファイルを作ります。
cat ./kms_key.conf KMSKeyId=YOUR_KMS_KEY_ID
スクリプトの内容はこんな感じです。
ebs_encrypt.sh
#!/bin/bash . ./kms_key.conf echo "What is TargetInstanceName?" read TargetInstanceName echo "Ok~" # 対象インスタンスIDを取得 TargetInstanceId=`aws ec2 describe-instances --filter "Name=tag:Name,Values=${TargetInstanceName}" \ | jq -r '.Reservations[].Instances[].InstanceId'` # 対象インスタンスのステータスを取得 InstanceStatus=`aws ec2 describe-instance-status --instance-ids $TargetInstanceId \ | jq -r '.InstanceStatuses[].InstanceState.Name'` if [ "$InstanceStatus" = "running" ]; then # 対象インスタンスのAMIを作成 AMIId=`aws ec2 create-image --instance-id $TargetInstanceId --name "Origin-AMI" --description "An AMI for my server" \ | jq -r '.ImageId'` # AMI作成の状態を確認 while [ "$ImageStatus" != "available" ] do sleep 10 ImageStatus=`aws ec2 describe-images --image-ids $AMIId | jq -r '.Images[].State'` echo $ImageStatus done echo "Image created." # AMIからコピーして暗号化AMI作成 EncryptedAMIId=`aws ec2 copy-image --encrypted --kms-key-id ${KMSKeyId} \ --source-image-id ${AMIId} --source-region ap-northeast-1 --name "EncryptedAMI" \ | jq -r '.ImageId'` # AMI作成の状態を確認 while [ "$EncryptedImageStatus" != "available" ] do sleep 10 EncryptedImageStatus=`aws ec2 describe-images --image-ids $EncryptedAMIId | jq -r '.Images[].State'` echo $EncryptedImageStatus done echo "EncryptedImage created." # AMIIDからスナップショットIDを取得 // 超絶雑。 EncryptedAMISnapId=`aws ec2 describe-snapshots --filters Name=description,Values="*${EncryptedAMIId}*" \ | jq -r '.Snapshots[].SnapshotId'` Result=`aws ec2 describe-snapshots --snapshot-ids $EncryptedAMISnapId \ | jq '.Snapshots[].Encrypted'` if [ "$Result" = "true" ]; then echo "Task is Done" else echo "Error! Something wrong..." >&2 fi else # 対象インスタンスのボリュームIDを取得 TargetVolumeId=`aws ec2 describe-instances --instance-ids $TargetInstanceId \ | jq -r '.Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId'` # moqrin-snapshotというSnapshotを作成 SnapshotId=`aws ec2 create-snapshot --volume-id $TargetVolumeId --tag-specifications 'ResourceType=snapshot,\ Tags=[{Key=Name,Value=moqrin-snapshot}]' \ | jq -r '.SnapshotId'` while [ "$SnapshotStatus" != "completed" ] do sleep 10 SnapshotStatus=`aws ec2 describe-snapshots --snapshot-id $SnapshotId | jq -r '.Snapshots[].State'` echo $SnapshotStatus done echo "Snapshot created." # スナップショットをコピーして暗号化する EncryptSnapId=`aws ec2 copy-snapshot --source-region ap-northeast-1 --source-snapshot-id $SnapshotId \ --encrypted --kms-key-id ${KMSKeyId} --description "Snapshot encrypted" \ | jq -r '.SnapshotId'` while [ "$EncryptSnapshotStatus" != "completed" ] do sleep 10 EncryptSnapshotStatus=`aws ec2 describe-snapshots --snapshot-id $EncryptSnapId | jq -r '.Snapshots[].State'` echo $EncryptSnapshotStatus done echo "EncryptSnap created." Result=`aws ec2 describe-snapshots --snapshot-ids $EncryptSnapId \ | jq -r '.Snapshots[].Encrypted'` if [ "$Result" = "true" ]; then echo "Task is Done" else echo "Error! Something wrong..." >&2 fi fi
対象のインスタンスが稼働中か停止中かで上記表の行に対応します。
なお、暗号化処理までしか実行していませんので、あしからず。
実行権限を付与しておきます。
$ sudo chmod a+x ./ebs_encrypt.sh
叩くとこんな感じです。
$ ./ebs_encrypt.sh What is TargetInstanceName? YOUR_INSTANCE_NAME Ok~
終わるとこんな感じです。 (AMIの作成は結構時間かかります。)
available EncryptedImage created. Task is Done
暗号化AMI
暗号化スナップショット
3 後片付けを忘れずに
無益なAMIとスナップショットは漏れなく削除しておきましょう。(特にスナップショット)
感想
KMSとの交友関係は、まだまだ浅い...。 そしてまたつまらぬスクリプトを書いてしまった...。